package com.biwin.module.security.starter.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.biwin.module.org.api.service.ISystemUserService;
import com.biwin.module.org.api.vo.PositionVo;
import com.biwin.module.org.api.vo.SystemUserVo;
import com.biwin.module.security.api.properties.BiWinSecurityProperties;
import com.biwin.module.security.api.service.BwUserDetailService;
import com.biwin.module.security.api.vo.BaseRoleVo;
import com.biwin.module.security.api.vo.BwUserDetailVo;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * extends Spring UserDetailsService
 *
 * @author biwin
 * @since 0.0.1
 */
public class BwUserDetailServiceImpl implements BwUserDetailService {

    private final ISystemUserService systemUserService;

    private final BiWinSecurityProperties securityProperties;

    public BwUserDetailServiceImpl(ISystemUserService systemUserService, BiWinSecurityProperties securityProperties) {
        this.systemUserService = systemUserService;
        this.securityProperties = securityProperties;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SystemUserVo user = systemUserService.findByAccount(username);
        //todo 获取当前登录用的权限
        //        List<BaseRoleVO> grantedAuths = accountPerviewService.getEnableRolesByUserId(user.getUserid());
        List<BaseRoleVo> grantedAuths = new ArrayList<>();
        List<PositionVo> positionList = user.getPositionList();
        if(CollUtil.isNotEmpty(positionList)){
            positionList.forEach(p-> grantedAuths.add(new BaseRoleVo(p)));
        }

//        Collection<? extends GrantedAuthority>  grantedAuths = systemUserService.getEnableRolesByUserId(user.getId());

//        Collection<? extends GrantedAuthority> grantedAuths = new ArrayList<>();
        boolean isEnabled = accountEnabled(user);
        boolean isAccountNonExpired = accountNonExpired(user);
        boolean isCredentialsNonExpired = true;
        boolean isAccountNonLocked = accountNonLocked(user);
        BwUserDetailVo bwUserDetailVo = new BwUserDetailVo(user.getAccount(), user.getPassword(), isEnabled, isAccountNonExpired,
                isCredentialsNonExpired, isAccountNonLocked, grantedAuths);
        bwUserDetailVo.setSystemUserVo(user);
        return bwUserDetailVo;
    }

    private boolean accountNonExpired(SystemUserVo user) {
        boolean result = true;
        if (securityProperties.getPasswordUsefulLife() > 0) {
            Date validDate = null;
            if (ObjectUtil.isEmpty(user.getPasswordLastModifyDate())) {
                validDate = user.getCreateTime();
            } else {
                validDate = user.getPasswordLastModifyDate();
            }

            DateUnit dateUnit =  DateUnit.DAY;
            switch (securityProperties.getLifeTimeUnit()) {
                case SECONDS:
                    dateUnit = DateUnit.SECOND;
                    break;
                case MINUTES:
                    dateUnit = DateUnit.MINUTE;
                    break;
                case HOURS:
                    dateUnit = DateUnit.HOUR;
                    break;
                default:
                    //默认用 days 解析
                    break;
            }
            if (DateUtil.between(new Date(), validDate, dateUnit) > securityProperties.getPasswordUsefulLife()) {
                result = false;
            }
        }
        return result;
    }

    private boolean accountEnabled(SystemUserVo user) {
        return user.getEffective() && !user.getDeleted();
    }

    public boolean accountNonLocked(SystemUserVo user) {
        return securityProperties.getPasswordUsefulLife() <= 0 || user.getPasswordFaultNum() < securityProperties.getPasswordMaxFailNumber();
    }
}
